package models;

import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.Vector;

import tools.HasInvariant;

public class WordStore implements HasInvariant {

	/**
	 * The words in the word store (with no repeated elements); and may be empty
	 * All words are written in lower case and letters restricted to lower case
	 * 'a'..'z'
	 */
	private Vector<String> allWords;

	/**
	 * The rng responsible for picking a word randomly
	 */
	private Random rng;

	public boolean invariant() {

		if (rng == null)
			return false;

		String word;
		Enumeration<String> e = allWords.elements();
		while (e.hasMoreElements()) {
			word = e.nextElement();
			for (int i = 0; i < word.length(); i++)
				if (word.charAt(i) < 'a' || word.charAt(i) > 'z')
					return false;
		}

		return true;
	}

	public WordStore() {
		allWords = new Vector<String>();
		rng = new Random();
	}

	public WordStore(Random rng) {
		allWords = new Vector<String>();
		if (rng == null)
			rng = new Random();
		this.rng = rng;
	}

	public WordStore(String[] strings) throws IllegalArgumentException {

		if (strings == null)
			throw new IllegalArgumentException(
					"Cannot make a wordstore with no words");
		allWords = new Vector<String>();

		for (int i = 0; i < strings.length; i++)
			addWord(strings[i]);
		rng = new Random();
	}

	public WordStore(Random rng, String[] strings)
			throws IllegalArgumentException {

		if (strings == null)
			throw new IllegalArgumentException(
					"Cannot make a wordstore with no words");
		allWords = new Vector<String>();

		for (int i = 0; i < strings.length; i++)
			addWord(strings[i]);
		if (rng == null)
			rng = new Random();
		else
			this.rng = rng;
	}

	public WordStore(Random rng, Set<String> strings) throws IllegalArgumentException {

		if (strings == null)
			throw new IllegalArgumentException(
					"Cannot make a wordstore with no words");
		allWords = new Vector<String>();

		Iterator<String> itr = strings.iterator();
		while (itr.hasNext()) {
			addWord(itr.next());
		}

		if (rng == null)
			rng = new Random();
		else
			this.rng = rng;
	}

	
	public WordStore(Random rng, Collection<String> strings) throws IllegalArgumentException {

		if (strings == null)
			throw new IllegalArgumentException(
					"Cannot make a wordstore with no words");
		allWords = new Vector<String>();

		Iterator<String> itr = strings.iterator();
		while (itr.hasNext()) {
			addWord(itr.next());
		}

		if (rng == null)
			rng = new Random();
		else
			this.rng = rng;
	}
	
	
	public boolean hasWord(String word) {

		return allWords.contains(word);
	}

	public void addWord(String nom) throws IllegalArgumentException {

		if (nom == null)
			throw new IllegalArgumentException(
					"Can't add a null string to the word store");

		for (int i = 0; i < nom.length(); i++)
			if (nom.charAt(i) < 'a' || nom.charAt(i) > 'z')
				throw new IllegalArgumentException(
						"Can't add a string with characters outside range a..z");

		if (hasWord(nom))
			return;

		allWords.addElement(nom);

	}

	public int numberOfWords() {

		return allWords.size();
	}

	public String toString() {

		return allWords.toString();
	}

	public String randomWord() throws IllegalStateException {

		int size = allWords.size();
		if (size == 0)
			throw new IllegalStateException(
					"Can't get a word from an empty word store");
		return allWords.elementAt(rng.nextInt(size));
	}
}
